package com.wdk.processor;

import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.JavaFile;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.ParameterSpec;
import com.squareup.javapoet.TypeName;
import com.squareup.javapoet.TypeSpec;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.util.Elements;


public class MtopAnnotationClass {
    private ArrayList<MtopSendField> mFields;//自定义注解的处理集合
    private TypeElement mTypeElement;
    private Elements mElements;

    private ArrayList<MethodSpec> bindViewBuidlers;//自定义注解的处理集合

    private ArrayList<MethodSpec> netRequestBuidlers;//自定义注解的处理集合


    public MtopAnnotationClass(TypeElement typeElement, Elements elements) {
        mFields = new ArrayList<>();
        bindViewBuidlers = new ArrayList<>();
        netRequestBuidlers = new ArrayList<>();
        this.mTypeElement = typeElement;
        this.mElements = elements;
    }

    /**
     * 保存有自定义注解的处理
     *
     * @param field
     */
    public void addField(MtopSendField field) {
        mFields.add(field);
    }


    /**
     * 核心
     * 利用开源javaPoet生成对应的.java代码
     *
     * @return
     */
    public JavaFile generateFiler() {


        try {
            //添加bindView方法的处理解析
            for (MtopSendField field : mFields) {

                String dataType = field.getDataType();

                System.out.println("创建方法: " + field.getMethodName().toString()+"  "+ dataType);

                if(null == dataType || dataType.equals(RequestDataType.LOCAL)) {
                    List<ParameterSpec> specList = field.getMethodParams();
                    //（1）生成java方法bindView：
                    MethodSpec.Builder bindViewBuidler = MethodSpec.methodBuilder(field.getMethodName().toString())
                            .addModifiers(Modifier.PUBLIC)//public
                            .addAnnotation(Override.class)//接口的复写方法
                            .addParameters(specList)
                            .returns(TypeUtil.PROVIDER);

                    bindViewBuidler.addStatement("$T params =new $T()"
                            , ClassName.get(HashMap.class)
                            , ClassName.get(HashMap.class));

                    bindViewBuidler.addStatement("params.put(\"API\",$S)"
                            , field.getApi());

                    bindViewBuidler.addStatement("params.put(\"VERSION\",$S)"
                            , field.getVersion());

                    for (ParameterSpec spec : specList) {
                        bindViewBuidler.addStatement("params.put(\"$N\"," + spec.name + ")"
                                , spec.name);
                    }

                    bindViewBuidler.addStatement("$T requestParams =new $T()"
                            , TypeUtil.PROVIDER
                            , TypeUtil.PROVIDER);

                    bindViewBuidler.addStatement("requestParams.setParams(params)"
                            , field.getApi());

                    bindViewBuidler.addStatement("return requestParams");

//                //三个参数
//                bindViewBuidler.addStatement("$T.sendMessage(params)"
//                        , ClassName.get(NetWorkUtils.class));
                    bindViewBuidlers.add(bindViewBuidler.build());
                }else {
                    List<ParameterSpec> specList = field.getMethodParams();
                    MethodSpec.Builder bindViewBuidler = MethodSpec.methodBuilder(field.getMethodName().toString())
                            .addModifiers(Modifier.PUBLIC)//public
                            .addAnnotation(Override.class)//接口的复写方法
                            .addParameters(specList)
                            .returns(TypeUtil.PROVIDER);

                    bindViewBuidler.addStatement("$T params =new $T()"
                            , ClassName.get(HashMap.class)
                            , ClassName.get(HashMap.class));

                    bindViewBuidler.addStatement("params.put(\"API\",$S)"
                            , field.getApi());

                    bindViewBuidler.addStatement("params.put(\"VERSION\",$S)"
                            , field.getVersion());

                    for (ParameterSpec spec : specList) {
                        bindViewBuidler.addStatement("params.put(\"$N\"," + spec.name + ")"
                                , spec.name);
                    }

                    bindViewBuidler.addStatement("$T requestParams =new $T()"
                            , TypeUtil.PROVIDER
                            , TypeUtil.PROVIDER);

                    bindViewBuidler.addStatement("requestParams.setParams(params)"
                            , field.getApi());

                    bindViewBuidler.addStatement("return requestParams");

//                //三个参数
//                bindViewBuidler.addStatement("$T.sendMessage(params)"
//                        , ClassName.get(NetWorkUtils.class));
                    bindViewBuidlers.add(bindViewBuidler.build());
                }


            }

            System.out.println("创建方法完事: " + "");

            //（3）生成java的类文件（.java的文件）
            TypeSpec injectClass = TypeSpec.classBuilder(mTypeElement.getSimpleName() + "Impl")
                    .addModifiers(Modifier.PUBLIC)
//                .addSuperinterface(ParameterizedTypeName.get(TypeUtil.BINDER, TypeName.get(mTypeElement.asType())))//类实现的接口名
                    .addSuperinterface(TypeName.get(mTypeElement.asType()))//类实现的接口名
                    .addMethods(bindViewBuidlers)
                    .build();
            //添加包名
            String packageName = mElements.getPackageOf(mTypeElement).getQualifiedName().toString();
            //JavaFile
            JavaFile result = JavaFile.builder(packageName, injectClass).build();


        //将打印也写入
            result.writeTo(System.out);

            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }


    /**
     * 反射调用对应的接口，需要的接口位置，包名：com.test.lib
     */
    private static class TypeUtil {

        static final ClassName PROVIDER = ClassName.get("com.test.testrequestfit", "RequestParams");




    }



}